package com.hq.security;

/**
 * 死锁产生的四个条件：
 * 1、互斥-资源排它：这个资源同一时间，只允许一个线程获取修改它（只读就不会出现在死锁）。
 * 2、占有并请求：获取到一个资源，还要再去获取其他资源。(该资源被另外的线程占用，另外的线程又在获取你的资源)。
 * 3、不可抢占：在获取到资源的过程中，不能被其他线程打断抢占（你获取时候出现异常，资源得不到释放，别的又一直等待）。
 * 4、资源之间的循环依赖：获取进程资源时，这个资源需要其他资源，头尾连接 导致进程资源闭环。
 * 死锁的解决思路：
 * 一、预防死锁：设置一些条件，破坏死锁的一个或者多个的产生条件。
 * 1、破坏互斥，资源排他（一般不会这样做 比如打印机 只能一个一个来）。
 * 2、破坏占有并请求：获取了一个锁资源后 不允许再去获取另外一个锁资源。（如果有这样的需求呢？）。
 * 2.1、一次性全分配：线程在获取资源的时候 把所有需要的资源一次性给它 不能全部获取就等待。
 * 2.2、线程在带有锁资源的情况下去获取别的资源时，规定线程要先释放掉自己占有的资源，才能取获取新的锁资源。
 * 3、破坏不可抢占：进程A请求一个资源 被进程B占用了，可以要求他释放资源（根据线程的优先级）
 * 4、破坏循环等待：给资源编号，并进行排序。
 * 5、银行家算法。
 * 5.1、判断 你请求的资源 <= 你需要的资源    不满足报错。
 * 5.2、判断 你请求的资源 <= 你能够获取的资源  不满足--进入等待期 直到获取到请求的所有资源
 * 5.3、系统试探将资源分配给该进程  安全性检测 通过后就分配  不通过 继续等待。
 * 二、检测死锁：
 * 三、尽量考虑到死锁的情况，避免死锁。
 * 1、加锁顺序：下面案例，只要线程Dead1 Dead2  获取资源顺序一样就不会有死锁了（局限性）
 * 2、限时加锁：在尝试获取资源的时候 等待一定的时间后 还没获取到 释放自己的资源 再去获取。synchronized不能设置超时
 * 四、检测死锁：通过算法找到死锁进程后，利用抢占、回滚、杀死进程方式进行恢复（这个不推荐）。jstack 可以查看
 *
 * @author hq
 */
public class DeadLockDemo {
    public static void main(String[] args) {
        Thread thread1 = new Thread(new DeadLockRunnable(1), "Dead1");
        Thread thread2 = new Thread(new DeadLockRunnable(2), "Dead2");
        thread1.start();
        thread2.start();
    }
}
